package cc.comac.saic.hkhy.jsrj.gj.inttools.service.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

import org.gitlab4j.api.GitLabApiException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cc.comac.saic.hkhy.jsrj.gj.common.mybatis.core.page.PageQuery;
import cc.comac.saic.hkhy.jsrj.gj.inttools.async.AsyncTaskExecutor;
import cc.comac.saic.hkhy.jsrj.gj.inttools.constant.AsyncTaskType;
import cc.comac.saic.hkhy.jsrj.gj.inttools.constant.FileType;
import cc.comac.saic.hkhy.jsrj.gj.inttools.gitlab.VersionManegeClient;
import cc.comac.saic.hkhy.jsrj.gj.inttools.mapper.FileInfoMapper;
import cc.comac.saic.hkhy.jsrj.gj.inttools.mapper.FileVersionInfoMapper;
import cc.comac.saic.hkhy.jsrj.gj.inttools.mapper.IntToolDataInfoMapper;
import cc.comac.saic.hkhy.jsrj.gj.inttools.mapper.IntToolDataRequirementMapper;
import cc.comac.saic.hkhy.jsrj.gj.inttools.mapper.ProjectInfoMapper;
import cc.comac.saic.hkhy.jsrj.gj.inttools.parser.IntToolDataParser;
import cc.comac.saic.hkhy.jsrj.gj.inttools.parser.IntToolDataReqInfo;
import cc.comac.saic.hkhy.jsrj.gj.inttools.parser.ParseResult;
import cc.comac.saic.hkhy.jsrj.gj.inttools.pojo.entity.FileInfo;
import cc.comac.saic.hkhy.jsrj.gj.inttools.pojo.entity.FileVersionInfo;
import cc.comac.saic.hkhy.jsrj.gj.inttools.pojo.entity.IntToolDataInfo;
import cc.comac.saic.hkhy.jsrj.gj.inttools.pojo.entity.IntToolDataRequirement;
import cc.comac.saic.hkhy.jsrj.gj.inttools.pojo.entity.ProjectInfo;
import cc.comac.saic.hkhy.jsrj.gj.inttools.pojo.vo.IntToolDataInfoSearchVo;
import cc.comac.saic.hkhy.jsrj.gj.inttools.pojo.vo.IntToolDataInfoShowVo;
import cc.comac.saic.hkhy.jsrj.gj.inttools.pojo.vo.IntToolDataRequirementShowVo;
import cc.comac.saic.hkhy.jsrj.gj.inttools.service.IntToolDataInfoService;
import cc.comac.saic.hkhy.jsrj.gj.system.service.impl.SysUserServiceImpl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import static cc.comac.saic.hkhy.jsrj.gj.inttools.constant.Constants.INT_TOOL_DATA_REQ_INFO;

/**
 * 工具链数据信息(IntToolDataInfo)表服务实现类
 *
 * @author makejava
 * @since 2025-11-18 17:13:04
 */
@Service
public class IntToolDataInfoServiceImpl extends ServiceImpl<IntToolDataInfoMapper, IntToolDataInfo> implements IntToolDataInfoService {
    @Autowired
    private IntToolDataParser intToolDataParser;
    @Autowired
    private FileInfoMapper fileInfoMapper;
    @Autowired
    private FileVersionInfoMapper fileVersionInfoMapper;
    @Autowired
    private AsyncTaskExecutor asyncTaskExecutor;
    @Autowired
    private IntToolDataInfoMapper intToolDataInfoMapper;
    @Autowired
    private IntToolDataRequirementMapper intToolDataRequirementMapper;
    @Autowired
    private VersionManegeClient versionManegeClient;
    @Autowired
    private ProjectInfoMapper projectInfoMapper;
    @Autowired
    private SysUserServiceImpl sysUserService;

    @Override
    public IntToolDataInfoShowVo queryById(Long id) {
        IntToolDataInfo intToolDataInfo = intToolDataInfoMapper.selectById(id);
        return intToolDataInfo2IntToolDataInfoShowVo(intToolDataInfo);
    }

    @Override
    public List<IntToolDataInfoShowVo> listNewestByCondition(IntToolDataInfoSearchVo intToolDataInfoSearchVo) {
        return intToolDataInfoMapper.queryNewestByCondition(intToolDataInfoSearchVo)
            .stream()
            .map(this::intToolDataInfo2IntToolDataInfoShowVo)
            .collect(Collectors.toList());
    }

    @Override
    public Page<IntToolDataInfoShowVo> pageByCondition(IntToolDataInfoSearchVo intToolDataInfoSearchVo, PageQuery pageQuery) {
        IPage<IntToolDataInfo> intToolDataInfoIPage = intToolDataInfoMapper.pageByCondition(pageQuery.build(), intToolDataInfoSearchVo);

        Page<IntToolDataInfoShowVo> intToolDataInfoShowVoPage = new Page<>();
        BeanUtil.copyProperties(intToolDataInfoIPage, intToolDataInfoShowVoPage);

        intToolDataInfoShowVoPage.setRecords(intToolDataInfoIPage.getRecords()
            .stream()
            .map(this::intToolDataInfo2IntToolDataInfoShowVo)
            .collect(Collectors.toList()));

        return intToolDataInfoShowVoPage;
    }


    @Override
    @Transactional
    public void parseAndSaveIntToolData(Long fileVersionId, Long operator) {
        Map<String, Object> taskParams = new HashMap<>();
        taskParams.put("fileVersionId", fileVersionId);

        asyncTaskExecutor.executeTask(
            AsyncTaskType.INT_TOOL_DATA_PARSE.getName(),
            AsyncTaskType.INT_TOOL_DATA_PARSE.getKey(),
            taskParams,
            operator,
            asyncTaskContext -> {
                FileVersionInfo fileVersionInfo = fileVersionInfoMapper.queryById(fileVersionId);
                if (Objects.isNull(fileVersionInfo)) {
                    throw new RuntimeException("数据文件不存在");
                }
                FileInfo fileInfo = fileInfoMapper.queryById(fileVersionInfo.getFileInfoId());
                ProjectInfo projectInfo = projectInfoMapper.queryById(fileInfo.getProjId());
                String fileContent = null;
                try {
                    fileContent = versionManegeClient.getFileContent(projectInfo.getProjKey(),
                        Objects.requireNonNull(FileType.getFileTypeByCode(fileInfo.getFileType())),
                        fileInfo.getFilePath(),
                        fileVersionInfo.getHash());
                } catch (GitLabApiException e) {
                    throw new RuntimeException("获取文件内容失败", e);
                }

                ParseResult parseResult = intToolDataParser.parseData(fileContent, FileType.getFileTypeByCode(fileInfo.getFileType()));
                if (!parseResult.isSuccess()) {
                    throw new RuntimeException();
                }


                // 清理上一次解析的数据
                List<IntToolDataInfo> intToolDataInfos = intToolDataInfoMapper.selectList(Wrappers.<IntToolDataInfo>lambdaQuery().eq(IntToolDataInfo::getFileVersionId, fileVersionInfo.getId()));
                intToolDataInfos.forEach(intToolDataInfo -> {
                    intToolDataInfoMapper.deleteById(intToolDataInfo.getId());
                    intToolDataRequirementMapper.delete(Wrappers.<IntToolDataRequirement>lambdaQuery().eq(IntToolDataRequirement::getIntToolDataId, intToolDataInfo.getId()));
                });


                List<IntToolDataReqInfo> intToolDataReqInfos = Optional.of(parseResult).map(result -> result.getField(INT_TOOL_DATA_REQ_INFO)).map(o -> new ArrayList<>((Collection<IntToolDataReqInfo>) o)).orElse(new ArrayList<>());
                Map<String, List<IntToolDataReqInfo>> id2IntToolDataReqInfos = intToolDataReqInfos.stream()
                    .filter(intToolDataReqInfo -> intToolDataReqInfo.getId() != null && intToolDataReqInfo.getRequirementItemId() != null)
                    .collect(Collectors.groupingBy(IntToolDataReqInfo::getId));
                id2IntToolDataReqInfos.forEach((id, tempIntToolDataReqInfos) -> {
                    IntToolDataInfo intToolDataInfo = new IntToolDataInfo();
                    tempIntToolDataReqInfos.stream().findAny().ifPresent(intToolDataReqInfo -> {
                        intToolDataInfo.setCode(intToolDataReqInfo.getId());
                        intToolDataInfo.setName(intToolDataReqInfo.getName());
                        intToolDataInfo.setDescription(intToolDataReqInfo.getDescription());
                        intToolDataInfo.setType(fileInfo.getFileType());
                        intToolDataInfo.setFileInfoId(fileVersionInfo.getFileInfoId());
                        intToolDataInfo.setFileVersionId(fileVersionId);
                        intToolDataInfo.setCreateBy(operator);
                        intToolDataInfo.setCreateTime(new Date());
                        intToolDataInfo.setUpdateBy(operator);
                        intToolDataInfo.setUpdateTime(new Date());
                        intToolDataInfoMapper.insert(intToolDataInfo);
                    });

                    tempIntToolDataReqInfos.forEach(intToolDataReqInfo -> {
                        IntToolDataRequirement intToolDataRequirement = new IntToolDataRequirement();
                        intToolDataRequirement.setIntToolDataId(intToolDataInfo.getId());
                        intToolDataRequirement.setRequirementId(intToolDataReqInfo.getRequirementId());
                        intToolDataRequirement.setRequirementItemId(intToolDataReqInfo.getRequirementItemId());
                        intToolDataRequirement.setCreateBy(operator);
                        intToolDataRequirement.setCreateTime(new Date());
                        intToolDataRequirement.setUpdateBy(operator);
                        intToolDataRequirement.setUpdateTime(new Date());
                        intToolDataRequirementMapper.insert(intToolDataRequirement);
                    });
                });
            });
    }

    private IntToolDataInfoShowVo intToolDataInfo2IntToolDataInfoShowVo(IntToolDataInfo intToolDataInfo) {
        IntToolDataInfoShowVo intToolDataInfoShowVo = new IntToolDataInfoShowVo();
        BeanUtil.copyProperties(intToolDataInfo, intToolDataInfoShowVo, CopyOptions.create().setIgnoreError(true));
        FileInfo fileInfo = fileInfoMapper.queryById(intToolDataInfo.getFileInfoId());
        FileVersionInfo fileVersionInfo = fileVersionInfoMapper.queryById(intToolDataInfo.getFileVersionId());
        intToolDataInfoShowVo.setFileName(fileInfo.getFilePath());
        intToolDataInfoShowVo.setFileVersionHash(fileVersionInfo.getHash());
        List<IntToolDataRequirementShowVo> intToolDataRequirements = intToolDataRequirementMapper.selectList(Wrappers.<IntToolDataRequirement>lambdaQuery().eq(IntToolDataRequirement::getIntToolDataId, intToolDataInfo.getId()))
            .stream().map(intToolDataRequirement -> {
                IntToolDataRequirementShowVo intToolDataRequirementShowVo = new IntToolDataRequirementShowVo();
                BeanUtil.copyProperties(intToolDataRequirement, intToolDataRequirementShowVo, CopyOptions.create().setIgnoreError(true));
                Optional.ofNullable(sysUserService.selectUserById(intToolDataRequirement.getCreateBy())).ifPresent(intToolDataRequirementShowVo::setCreateBy);
                Optional.ofNullable(sysUserService.selectUserById(intToolDataRequirement.getUpdateBy())).ifPresent(intToolDataRequirementShowVo::setUpdateBy);

                return intToolDataRequirementShowVo;
            }).collect(Collectors.toList());
        intToolDataInfoShowVo.setIntToolDataRequirements(intToolDataRequirements);
        Optional.ofNullable(sysUserService.selectUserById(intToolDataInfo.getCreateBy())).ifPresent(intToolDataInfoShowVo::setCreateBy);
        Optional.ofNullable(sysUserService.selectUserById(intToolDataInfo.getUpdateBy())).ifPresent(intToolDataInfoShowVo::setUpdateBy);
        return intToolDataInfoShowVo;
    }
}

